﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Data.Common;
using System.Data.SqlClient;
using Ict.DataAccess;
using Ict.DataAccess.Attributes;
using Ict.DataAccess.Conditions;
using System.Reflection;
using System.Linq;

namespace Ict.DataAccess.SqlServer
{
    /// <summary>
    /// Executor的MS Sql Server版本
    /// </summary>
    public class SqlExecutor : Executor
    {
        public SqlExecutor(string connectionString) : base(connectionString)
        {
            
        }

        #region Executor members

        /// <summary>
        /// 创建一个新的数据库连接，本方法用于类构造函数中，创建一个实例化的连接对象
        /// </summary>
        /// <returns>数据库连接类的实例</returns>
        protected override DbConnection NewConnection()
        {
            return new SqlConnection();
        }

        /// <summary>
        /// 创建一个新的数据库数据适配器
        /// </summary>
        /// <returns></returns>
        protected override DbDataAdapter NewDataAdapter()
        {
            return new SqlDataAdapter();
        }

        /// <summary>
        /// 创建一个新的数据库命令对象
        /// </summary>
        /// <returns></returns>
        protected override DbCommand NewCommand()
        {
            return new SqlCommand();
        }

        public override DataList<T> Query<T>(Condition condition, params Sort[] sortings)
        {
            SqlDmlBuilder builder = new SqlDmlBuilder();

            // 读取T类的QueryName和QueryFields参数
            Type type = typeof(T);
            object[] attrs = type.GetCustomAttributes(typeof(QueryNameAttribute), false);
            if (attrs.Length == 0)
                throw new Exception("QueryName attribute is not provided.");
            QueryNameAttribute qname = attrs[0] as QueryNameAttribute;

            attrs = type.GetCustomAttributes(typeof(QueryFieldsAttribute), false);
            string[] fieldList = null;
            if (attrs.Length == 0)
                fieldList = new string[] { "*" };
            else
                fieldList = (attrs[0] as QueryFieldsAttribute).Value;

            string sql = builder.BuildQuery(fieldList, qname.Value, condition, sortings);

            return Query<T>(sql);
        }

        /// <summary>
        /// 插入一条记录
        /// </summary>
        /// <param name="data">实体类实例</param>
        /// <param name="tableName">实体对应表名</param>
        /// <returns>受影响行数</returns>
        public override int Insert(DataEntity data, string tableName)
        {
            SqlDmlBuilder builder = new SqlDmlBuilder();
            string sql = builder.BuildInsert(data, tableName);

            return this.Execute(sql);
        }

        /// <summary>
        /// 更新符合条件的记录行
        /// </summary>
        /// <param name="data">实体类实例</param>
        /// <param name="tableName">实体对应表名</param>
        /// <param name="condition">更新筛选条件</param>
        /// <returns>受影响行数</returns>
        public override int Update(DataEntity data, string tableName, Condition condition)
        {
            SqlDmlBuilder builder = new SqlDmlBuilder();
            string sql = builder.BuildUpdate(data, tableName, condition);

            return this.Execute(sql);
        }

        /// <summary>
        /// 删除符合条件的记录行
        /// </summary>
        /// <param name="tableName">实体对应表名</param>
        /// <param name="condition">删除筛选条件</param>
        /// <returns>受影响行数</returns>
        public override int Delete(string tableName, Condition condition)
        {
            SqlDmlBuilder builder = new SqlDmlBuilder();
            string sql = builder.BuildDelete(tableName, condition);

            return this.Execute(sql);
        }

        public override int Insert<T>(T entity, string sql)
        {
            int n = 0;
            try
            {
                n = base.Insert<T>(entity, sql);
                Type type = typeof(T);
                PropertyInfo[] propInfos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                foreach(PropertyInfo propInfo in propInfos)
                {
                    object[] attrs = propInfo.GetCustomAttributes(typeof(IdentityFieldAttribute), true);
                    if (attrs !=null && attrs.Length > 0)
                    {
                        object oid = ExecuteScalar("SELECT SCOPE_IDENTITY()");
                        propInfo.SetValue(entity, Convert.ToInt32(oid), null);
                        break;
                    }
                }
            }
            catch (SqlException e)
            {
                if (e.Number == 2627)
                    throw new PrimaryKeyException(e);
                else
                    throw e;
            }
            return n;
        }

        /// <summary>
        /// 插入一条记录，对于带Identity字段的表，自动查询当前Identity，并对此字段赋值
        /// </summary>
        /// <typeparam name="T">记录的实体类型</typeparam>
        /// <param name="t">实体类实例</param>
        /// <returns>受影响行数</returns>
        public override int Insert<T>(T t)
        {
            string idFieldName = null;

            Type type = typeof(T);
            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (PropertyInfo info in propertyInfos)
            {
                object[] attrs = info.GetCustomAttributes(false);

                foreach(object attr in attrs)
                {
                    if (attr is IdentityFieldAttribute)
                    {
                        idFieldName = (attr as IdentityFieldAttribute).Value;
                        if (null == idFieldName)
                            idFieldName = info.Name;
                        t.AssignValues.Remove(idFieldName);
                        break;
                    }
                }
            }

            int nRet = base.Insert<T>(t);

            if (null != idFieldName)
            {
                t[idFieldName] = ExecuteScalar("SELECT SCOPE_IDENTITY()");
            }

            return nRet;
        }

        /// <summary>
        /// 更新符合条件的记录行
        /// </summary>
        /// <typeparam name="T">记录的实体类型</typeparam>
        /// <param name="t">实体类实例</param>
        /// <param name="condition">更新筛选条件</param>
        /// <returns>受影响行数</returns>
        public override int Update<T>(T t, Condition condition)
        {
            Type type = typeof(T);
            PropertyInfo[] propertyInfos = type.GetProperties();
            foreach (PropertyInfo info in propertyInfos)
            {
                object[] attrs = info.GetCustomAttributes(false);

                foreach (object attr in attrs)
                {
                    if (attr is IdentityFieldAttribute)
                    {
                        string filedName = (attr as IdentityFieldAttribute).Value;
                        if (null == filedName)
                            filedName = info.Name;
                        t.AssignValues.Remove(filedName);
                    }
                }
            }

            return base.Update(t, condition);
        }

        #endregion Executor members
    }
}
